﻿using System;
using System.Collections.Generic;
using System.ComponentModel;
using System.Linq;
using System.Text;
using System.Threading;
using System.Timers;
using GeneralDFS.BusinessLogical.NodeOperate;
using GeneralDFS.Common;
using GeneralDFS.DataEntity.Enum;

namespace GeneralDFS.BusinessLogical.Nodes
{
    public partial class DataNode
    {
        private readonly BackgroundWorker _backgroundHeartBeat = new BackgroundWorker();
        private readonly System.Timers.Timer _timerGetNameNode = new System.Timers.Timer();

        private void StartHeartBeat()
        {
            _backgroundHeartBeat.DoWork += _backgroundHeartBeat_DoWork;
            _backgroundHeartBeat.WorkerSupportsCancellation = true;
            _backgroundHeartBeat.RunWorkerAsync();
            _timerGetNameNode.Interval = 2000;
            _timerGetNameNode.Elapsed += TimerGetNameNodeOnElapsed;
            _timerGetNameNode.Start();
        }

        private void TimerGetNameNodeOnElapsed(object sender, ElapsedEventArgs elapsedEventArgs)
        {
            if (!NameNode.IsInstanceValid(NameNodeRemoteObject) || _nameNodeInfo.ID != NameNodeRemoteObject.ID)
            {
                _nameNodeInfo = NameNode.GetInstance(Config.NameNodeInfos()[0])
                    .FindSuccessor(DFSUtils.GetHash(Config.DetailConfig.HeartBeatHash));
                NameNodeRemoteObject = NameNode.GetInstance(_nameNodeInfo);
                NameNodeRemoteObject.RegisterDataNode(DataNodeInfo);
                LogUtil.LogInfo("_backgroundGetNameNode_DoWork NameNode: serverName:{0} ip:{1} rpcPort:{2}", _nameNodeInfo.ServerName, _nameNodeInfo.Ip, _nameNodeInfo.RpcPort);
            }
            //time must not too short
            Thread.Sleep(2000);
        }

        void _backgroundHeartBeat_DoWork(object sender, DoWorkEventArgs e)
        {
            var worker = (BackgroundWorker) sender;
            while (!worker.CancellationPending)
            {
                NameNodeRemoteObject.UpdateHeartBeat(DataNodeInfo.Name, DataNodeInfo.RpcPort, DataNodeInfo.TcpPort,
                                                     DataNodeInfo.Ip, 0, 0);
                var command = NameNodeRemoteObject.GetCommand(DataNodeInfo.Name);
                var operate = JudgeNodeOperate.GetNodeOperate(command);

                if (operate == null) return;
                operate.ChangeDataNode(this);
                operate.Operate();

                if (NameNodeRemoteObject.GetNameNodeState() == NameNodeState.SafeMode)
                {
                    //todo 上传文件块列表到NameNode
                    //调用方法NameNodeRemoteObject.AddBlockToDataNodeList(datanodeid, fileBlockInfo);
                }
                

                Thread.Sleep(Config.DetailConfig.HeartBeat);
            }
        }

        private void StopHeartBeat()
        {
            _backgroundHeartBeat.CancelAsync();
            _timerGetNameNode.Stop();
        }
    }
}
